package com.jeesit.cloud.spot.web.api_controller.title;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeesit.cloud.annotation.ModuleLog;
import com.jeesit.cloud.constants.LogConstant;
import com.jeesit.cloud.dto.*;
import com.jeesit.cloud.model.*;
import com.jeesit.cloud.spot.business.impl.ITitleBiz;
import com.jeesit.cloud.spot.service.*;
import com.jeesit.cloud.util.ExportExcel;
import com.jeesit.cloud.validate.CreateAction;
import com.jeesit.cloud.validate.QueryAction;
import com.jeesit.cloud.validate.UpdateAction;
import com.jeesit.cloud.verify.UserAuthDetail;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Size;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 *   相关接口
 *　　
 *   @description Title 接口
 *   ---------------------------------
 *   @author 漆传涛
 *   @date 2024-01-09
 */
@Slf4j
@RestController
@RequestMapping("/api/auth/v1/title")
@Api(tags = {"客商管理、我方抬头"})
public class TitleController {

    @Autowired
    private ITitleService titleService;
    @Autowired
    private ITitleInvoiceService titleInvoiceService;
    @Autowired
    private ITitleCommerceService titleCommerceService;
    @Autowired
    private ITitleAccountService titleAccountService;
    @Autowired
    private ITitleLinkmanService titleLinkmanService;

    @Autowired
    private ITitleBiz titleBiz;

    /**
     * @description 获取分页列表
     * ---------------------------------
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("获取分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "pageNo", value = "页码", dataTypeClass = Integer.class , paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页行数，最少10条，最多100条", dataTypeClass = Integer.class , paramType = "query", required = true)
    })
    //@PreAuthorize("hasAnyAuthority('SUPER_ADMIN','BACKGROUND_USER','COMPANY_USER','INDIVIDUAL_USER','SSE_USER')")
    @PostMapping(value = "/title_page")
    public JSONResult<Page<Title>> getTitlePage(Authentication authentication,@Validated(QueryAction.class)TitleDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        Page<Title> page=new Page<Title>(dto.getPageNo(), dto.getPageSize());
        titleService.page(page,dto);
        JSONResult<Page<Title>> res = new JSONResult<>();
        res.setMessage("");
        res.setSuccess(true);
        res.setData(page);
        return res;
    }

/**
     * @description 获取列表
     * ---------------------------------
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("获取列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "size", value = "查询数量，最多查询1000条", dataTypeClass = Integer.class, paramType = "query", required = true)
    })
    //@PreAuthorize("hasAnyAuthority('SUPER_ADMIN','BACKGROUND_USER','COMPANY_USER','INDIVIDUAL_USER','SSE_USER')")
    @PostMapping(value = "/title_list")
    public JSONResult<Title> getTitleList(Authentication authentication, @Validated(QueryAction.class)TitleDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        List<Title> list = titleService.list(dto.getSize(),dto);
        for(Title it : list){
            TitleAccountDto titleAccountDto = new TitleAccountDto();
            titleAccountDto.setTitleUuid(it.getUuid());
            List<TitleAccount> titleAccounts = titleAccountService.list(0, titleAccountDto);
            it.setTitleAccounts(titleAccounts);
            TitleCommerceDto titleCommerceDto = new TitleCommerceDto();
            titleCommerceDto.setTitleUuid(it.getUuid());
            List<TitleCommerce> titleCommerces = titleCommerceService.list(1, titleCommerceDto);
            it.setTitleCommerce(titleCommerces.size()>0?titleCommerces.get(0):new TitleCommerce());
            TitleLinkmanDto titleLinkmanDto = new TitleLinkmanDto();
            titleLinkmanDto.setTitleUuid(it.getUuid());
            it.setTitleLinkmans(titleLinkmanService.list(0,titleLinkmanDto));
            TitleInvoiceDto titleInvoiceDto = new TitleInvoiceDto();
            titleInvoiceDto.setTitleUuid(it.getUuid());
            List<TitleInvoice> titleInvoices = titleInvoiceService.list(1, titleInvoiceDto);
            it.setTitleInvoice(titleInvoices.size()>0?titleInvoices.get(0):new TitleInvoice());
        }
        JSONResult<Title> res = new JSONResult<>();
        res.setMessage("");
        res.setSuccess(true);
        res.setDatas(list);
        return res;
    }


    /**
     * @description 导出列表
     * ---------------------------------
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("导出列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('Title_Export','SUPER_ADMIN')")
    @PostMapping(value = "/title_export")
    public void export(HttpServletResponse response,Authentication authentication, @Validated(QueryAction.class)TitleDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        List<Title> datas = titleService.list(0,dto);
        String[] header = new String[]{"","简称","全称","社会信用代码","类型 0 客户 1 我方抬头","客户类型","父节点ID","节点路径","组织机构ID","业务部门id","营业执照路径","备注","创建时间","创建人","创建人id","修改时间","修改人","修改人id","",""};
        List<List<Object>> list = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        DecimalFormat df = new DecimalFormat("0.00");
        for(Title it : datas){
            List<Object> data = new ArrayList<>();
            data.add(it.getUuid());
            data.add(it.getShortName());
            data.add(it.getFullName());
            data.add(it.getCode());
            data.add(it.getCompanyType());
            data.add(it.getParentUuid());
            data.add(it.getTreePath());
            data.add(it.getOrgUuid());
            data.add(it.getBizOrgUuid());
            data.add(it.getPath());
            data.add(it.getRemark());
            data.add(Optional.ofNullable(it.getAddTime()).map(s->sdf.format(s)).orElse(""));
            data.add(it.getAddUserName());
            data.add(it.getAddUserUuid());
            data.add(Optional.ofNullable(it.getModTime()).map(s->df.format(s)).orElse(""));
            data.add(it.getModUserName());
            data.add(it.getModUserUuid());
            data.add(it.getDeleted());
            list.add(data);
        }
        ExportExcel excel = new ExportExcel();
        excel.setName("");
        excel.exportToExcel(response,header,list,0);
    }

    /**
     * @description 新建
     *
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("新建")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('Title_Add','TitleTwo_Add','SUPER_ADMIN')")
    @ModuleLog("Title")
    @PostMapping("/title_add")
    public JSONResult<Title> saveNewEntity(HttpServletRequest request,Authentication authentication, @Validated(CreateAction.class) TitleDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Title> res=titleBiz.saveData(user,null,entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "保存，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }

    /**
     * @description 更新
     *
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("更新 ")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('Title_Modify','TitleTwo_Modify','SUPER_ADMIN')")
    @ModuleLog("Title")
    @PostMapping("/title_edit")
    public JSONResult<Title> saveEditEntity(HttpServletRequest request,Authentication authentication,@Validated(UpdateAction.class) TitleDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Title> res= titleBiz.saveData(user,entity.getUuid(),entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "更新，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }

    private JSONResult<Title> saveData(User user,Long id,TitleDto entity){
        JSONResult<Title> res = new JSONResult<>();
        Title it = new Title();
        if(id==null){
            it.setDeleted(false);
        } else {
            it = titleService.getById(entity.getUuid());
        }
        it.setUuid(entity.getUuid());
        it.setShortName(entity.getShortName());
        it.setFullName(entity.getFullName());
        it.setCode(entity.getCode());
        it.setCompanyType(entity.getCompanyType());
        it.setParentUuid(entity.getParentUuid());
        it.setTreePath(entity.getTreePath());
        it.setOrgUuid(entity.getOrgUuid());
        it.setBizOrgUuid(entity.getBizOrgUuid());
        it.setPath(entity.getPath());
        it.setRemark(entity.getRemark());
        it.setAddTime(entity.getAddTime());
        it.setAddUserName(entity.getAddUserName());
        it.setAddUserUuid(entity.getAddUserUuid());
        it.setModTime(entity.getModTime());
        it.setModUserName(entity.getModUserName());
        it.setModUserUuid(entity.getModUserUuid());
        it.setDeleted(entity.getDeleted());
        titleService.saveOrUpdate(it);
        res.setData(it);
        res.setSuccess(true);
        res.setMessage("保存成功");
        return res;
    }


    /**
     * @description 删除
     *
     * @author 漆传涛
     * @date 2024-01-09
     */
    @ApiOperation("删除")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
        @ApiImplicitParam(name = "ids", value = "删除id（支持批量删除）", dataTypeClass = Long.class , allowMultiple = true,paramType = "query", required = true),
    })
    @PreAuthorize("hasAnyAuthority('Title_Remove','TitleTwo_Remove','SUPER_ADMIN')")
    @ModuleLog("Title")
    @PostMapping("title_del")
        public JSONResult<Void> delEntity(HttpServletRequest request,Authentication authentication,@Size(min=1,max=50,message = "请选择要删除数据") Long[] ids) throws Exception{
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Void> res = new JSONResult<>();
        for(int i=0;i<ids.length;i++){
            Title it = titleService.getById(ids[i]);
            titleService.removeById(it.getUuid());
        }
        request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "删除，数据ID:" + StringUtils.join(ids)));
        res.setMessage("删除成功");
        res.setSuccess(true);
        return res;
    }

    @ApiOperation("获取我方抬头树形结构")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "size", value = "查询数量，最多查询1000条", dataTypeClass = Integer.class, paramType = "query", required = true),
    })
    @PostMapping(value = "/title_tree_list")
    public JSONResult<Title> getTitleTreeList(Authentication authentication, TitleDto dto) {
        User user = ((UserAuthDetail) authentication.getPrincipal()).getUser();
        dto.setTreePath("0,");
        dto.setCompanyType(1);
        List<Title> list = titleService.list(0, dto);
        List<Title> treeRes = getTitleTrees(list);

        Title title1 = new Title();
        title1.setFullName("全部");
        title1.setUuid(0L);
        title1.setChildren(treeRes);
        JSONResult<Title> res = new JSONResult<>();
        res.setMessage("");
        res.setSuccess(true);
        res.setData(title1);
        return res;
    }

    @org.jetbrains.annotations.NotNull
    private List<Title> getTitleTrees(List<Title> list) {
        //所有分类id集合
        List<Long> idList = list.stream().map(Title::getUuid).collect(Collectors.toList());
        //返回的树分类结果
        List<Title> treeRes = new ArrayList<>();
        //一级分类目录
        List<Title> firstItem = list.stream()
                .filter(item -> !idList.contains(item.getParentUuid()))
                .collect(Collectors.toList());
        //循环当前一级分类目录
        for (Title item : firstItem) {
            //给当前分类节点 添加 子分类节点
            addChild(list, item);
            //当前分类添加完子节点分类之后，添加到返回的树结构中
            treeRes.add(item);
        }
        return treeRes;
    }

    /**
     * 给当前分类节点 添加 子分类节点
     *
     * @param
     * @param
     */
    public static void addChild(List<Title> titleList, Title title) {
        //循环所有的分类，获取当前节点的所有子节点
        List<Title> listChild = titleList.stream()
                .filter(item -> item.getParentUuid().equals(title.getUuid()))
                .collect(Collectors.toList());
        //把当前分类的子节点添加到当前分类
        title.setChildren(listChild);
        //再次调用本方法,把当前节点的子节点当成当前节点，继续添加子节点,备注：这样会造成一直循环
        listChild.forEach(item -> {
            //添加一步，判断当前节点是否有子节点，没有就不循环递归
            if (haveChild(titleList, item)) {
                addChild(titleList, item);
            }
        });
    }

    /**
     * 判断当前节点 是否存在 子节点
     *
     * @param titleList 所有的分类
     * @param title     当前节点
     */
    public static boolean haveChild(List<Title> titleList, Title title) {
        //获取当前节点的子节点
        List<Title> listChild = titleList.stream()
                .filter(item -> item.getParentUuid().equals(title.getUuid()))
                .collect(Collectors.toList());
        //子节点大于0则存在，否则不存在
        return listChild.size() > 0;
    }

}

